/*
 * Copyright (c) 2008-2011, Petr Panteleyev
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *    1. Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright notice,
 *       this list of conditions and the following disclaimer in the documentation
 *       and/or other materials provided with the distribution.
 *    3. The name of the author may not be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.panteleyev.wordpress;

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;

import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.SwingWorker;
import javax.swing.table.AbstractTableModel;

import org.panteleyev.blogapi.Blog;
import org.panteleyev.blogapi.BlogEntry;
import org.panteleyev.blogapi.MetaWeblogEntry;
import org.panteleyev.blogapi.WordPressAccount;
import org.panteleyev.blogclient.BloggerHistoryFrame;
import org.panteleyev.blogclient.BloggingKit;
import org.panteleyev.blogclient.MainClass;
import org.panteleyev.blogclient.Options;
import org.panteleyev.blogclient.events.PostDeletedEvent;
import org.panteleyev.swing.ClipboardUtil;
import org.panteleyev.swing.OSUtil;
import org.panteleyev.swing.SwingFactory;
import org.panteleyev.swing.SwingWorkerEx;
import org.panteleyev.swing.TableUtil;
import org.panteleyev.swing.events.UpdateFrameEvent;

public class WPHistoryFrame extends BloggerHistoryFrame<WordPressUserProfile,MetaWeblogEntry> {
    private static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd kk:mm");
    public static final int MAX_RES_DEFAULT = 20;

    private WordPressAccount           account;

    // Actions
    private AbstractAction      viewCommentsAction;
    private AbstractAction      copyEntryLinkAction;
    private AbstractAction      openEntryLinkAction;

    private int                 _maxResults;

    private final String[] historyTableHeaderNames = {
        " ",
        getTableDateColumnHeader(),
        getTableSubjectColumnHeader(),
        "C",
    };

    // Controls
    private JComboBox<String>   blogsComboBox;
    private JComboBox<Integer>  lastComboBox;

    private class HistoryUpdateThread extends SwingWorkerEx<Boolean,Object> {
        public HistoryUpdateThread() {
            super(WPHistoryFrame.this, getBusyLabel());
            enableActions(false);
        }

        @Override
        protected Boolean doInBackground() throws Exception {
            int blogIndex = blogsComboBox.getSelectedIndex();
            Blog blog = getAccount().getBlog(blogIndex);

            try {
               _maxResults = (Integer)lastComboBox.getSelectedItem();
            } catch (NumberFormatException e) {
                _maxResults = MAX_RES_DEFAULT;
            }

            setHistory(getAccount().getEntries(blog, _maxResults));
            return null;
        }

        @Override
        protected void done() {
            try {
                get();
                getTableModel().fireTableDataChanged();
                TableUtil.adjustTableColumnSizes(getTable(), 2, getScroller());
            } catch (InterruptedException | ExecutionException ex) {
                handleException(ex);
            } finally {
                enableActions(true);
                super.done();
            }
        }
    }

    private class DeleteEventsThread extends SwingWorker<Object,Object> {
        private int[] rows;
        private ArrayList<BlogEntry> toDelete;

        DeleteEventsThread(int[] rows) {
            this.rows = rows;
            toDelete = new ArrayList<>(rows.length);
            enableActions(false);
            setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
        }

        @Override
        protected Object doInBackground() throws Exception {
            /* Delete events from account */
            for (int index : rows) {
                try {
                    BlogEntry entry = getHistory().get(index);
                    getAccount().deleteEntry(entry);
                    toDelete.add(entry);
                } catch (Exception e) {
                }
            }

            return null;
        }

        @Override
        protected void done() {
            for (BlogEntry entry : toDelete) {
                getProfile().sendApplicationEvent(new PostDeletedEvent(this, entry));
                getHistory().remove(entry);
            }
            getTableModel().fireTableDataChanged();

            setCursor(Cursor.getDefaultCursor());
            enableActions(true);
        }
    }


    public WPHistoryFrame(WordPressUserProfile profile) {
        super(profile);
        this.account = profile.getAccount();

        _maxResults = MAX_RES_DEFAULT;

        initComponents();
        createMenuBar();
        createPopupMenu();

        createHistoryTable();

        receive(new UpdateFrameEvent(this));

        Options.getBounds(this);
    }

    private void initComponents() {
        getContentPane().setLayout(new BorderLayout());

        getContentPane().add(
            SwingFactory.createToolBarPanel(
                createProfileToolBar(false, true),
                Box.createHorizontalStrut(5),
                blogsComboBox = new JComboBox<>(new BlogComboBoxModel(getAccount().getBlogs())),
                Box.createHorizontalStrut(5),
                new JLabel(getLastLabel()),
                Box.createHorizontalStrut(3),
                lastComboBox = new JComboBox<>(new Integer[] {10, 20, 30, 40, 50}),
                Box.createHorizontalGlue(),
                SwingFactory.createToolBar(false, true, getUpdateAction()),
                Box.createHorizontalStrut(5),
                getBusyLabel(),
                Box.createHorizontalStrut(5)
            ), BorderLayout.NORTH
        );

        blogsComboBox.setSelectedIndex(0);
        lastComboBox.setSelectedIndex(1);

        SwingFactory.setWidthMaximumToPreferred(blogsComboBox, lastComboBox);

        getContentPane().add(getScroller(), BorderLayout.CENTER);
    }

    public WordPressAccount getAccount() {
        return this.account;
    }

    @Override
    public void update() {
        new HistoryUpdateThread().execute();
    }

    @Override
    protected void createActions() {
        super.createActions();

        viewCommentsAction = new ViewCommentsAction() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onViewComments();
            }
        };
        addAction(viewCommentsAction);

        copyEntryLinkAction = new BloggingKit.HistoryWindowCopyEntryLinkAction() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onCopyEntryLink();
            }
        };
        addAction(copyEntryLinkAction);

        openEntryLinkAction = new BloggingKit.HistoryWindowOpenEntryLinkAction() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onOpenEntryLink();
            }
        };
        addAction(openEntryLinkAction);
    }

    private void createMenuBar() {
        createMenuBar(
            createFileMenu(),
            createMenu(getHistoryMenuName(), null,
                getEditEventAction(),
                getDeleteEventAction(),
                null,
                viewCommentsAction,
                null,
                copyEntryLinkAction,
                openEntryLinkAction,
                null,
                getExportEventsAction()
            ),
            createProfileMenu(),
            createToolsMenu(),
            createWindowMenu(),
            createHelpMenu()
        );
    }

    private void createPopupMenu() {
        getScroller().setComponentPopupMenu(createMenu(null, null,
            getEditEventAction(),
            getDeleteEventAction(),
            null,
            viewCommentsAction,
            null,
            copyEntryLinkAction,
            openEntryLinkAction,
            null,
            getExportEventsAction()
        ).getPopupMenu());
    }

    private String getLinkOfSelectedEntry() {
        int row = getTable().getSelectedRow();
        if (row != -1) {
            BlogEntry event = getHistory().get(row);
            if ((event != null) && (!event.isDraft())) {
                return event.getLink();
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    private void onCopyEntryLink() {
        ClipboardUtil.put(getLinkOfSelectedEntry());
    }

    private void onOpenEntryLink() {
        String url = getLinkOfSelectedEntry();
        if (url != null) {
            OSUtil.runBrowser(url);
        }
    }

    private void onViewComments() {
        int row = getTable().getSelectedRow();
        if (row != -1) {
            BlogEntry event = getHistory().get(row);
            if (event != null && !event.isDraft()) {
                getProfile().openCommentsWindow(event);
            }
        }
    }

    @Override
    protected void editEvent() {
        int index = getTable().getSelectedRow();
        if (index != -1) {
            MetaWeblogEntry entry = getHistory().get(index);
            new WPOpenPostThread(getProfile(), entry).execute();
        }
    }

    @Override
    protected void deleteEvent() {
        final int[] rows = getTable().getSelectedRows();
        if (rows.length == 0) {
            return;
        }

        if (!MainClass.showConfirmDialog(this)) {
            return;
        }

        new DeleteEventsThread(rows).execute();
    }

    private void createHistoryTable() {
        setTableModel(new AbstractTableModel() {
            @Override
            public int getColumnCount() {
                return historyTableHeaderNames.length;
            }

            @Override
            public int getRowCount() {
                return getHistory().size();
            }

            @Override
            public Object getValueAt(int row, int col) {
                BlogEntry e = getHistory().get(row);

                switch (col) {
                    case 0:
                        return (e.isDraft())? "D" : "";
                    case 1:
                        return dateFormat.format(e.getDateCreated());
                    case 2:
                        return e.getSubject();
                    default:
                        return null;
                }
            }

            @Override
            public String getColumnName(int column) {
                return historyTableHeaderNames[column];
            }
        });
    }

}
